﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PortManage
{
    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            InitializeComponent();
        }

        #region 端口检测
        /// <summary>
        /// 获取操作系统已用的端口号
        /// </summary>
        /// <returns></returns>
        private IList PortIsUsed()
        {
            //获取本地计算机的网络连接和通信统计数据的信息
            IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();

            //返回本地计算机上的所有Tcp监听程序
            IPEndPoint[] ipsTCP = ipGlobalProperties.GetActiveTcpListeners();

            //返回本地计算机上的所有UDP监听程序
            IPEndPoint[] ipsUDP = ipGlobalProperties.GetActiveUdpListeners();

            //返回本地计算机上的Internet协议版本4(IPV4 传输控制协议(TCP)连接的信息。
            TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

            IList allPorts = new ArrayList();
            foreach (IPEndPoint ep in ipsTCP) allPorts.Add(ep.Port);
            foreach (IPEndPoint ep in ipsUDP) allPorts.Add(ep.Port);
            foreach (TcpConnectionInformation conn in tcpConnInfoArray) allPorts.Add(conn.LocalEndPoint.Port);

            return allPorts;
        }

        /// <summary>
        /// 检查指定端口是否已用
        /// </summary>
        /// <param name="port"></param>
        /// <returns></returns>
        private bool PortIsAvailable(int port)
        {
            bool isAvailable = true;

            IList portUsed = PortIsUsed();

            foreach (int p in portUsed)
            {
                if (p == port)
                {
                    isAvailable = false; break;
                }
            }

            return isAvailable;
        }
        #endregion

        #region 加载DGVPortTable本地所有端口数据
        private void initDGVPortTable()
        {
            DataTable dt = new DataTable();

            dt.Columns.Add("Port", typeof(int));
            dt.Columns.Add("IsUsed", typeof(string));
            dt.Columns.Add("Time", typeof(DateTime));

            int MAX_PORT = 65535;
            int BEGIN_PORT = 4999;

            for (int i = BEGIN_PORT; i <= MAX_PORT; i++)
            {
                DataRow dr2 = dt.NewRow();
                if (PortIsAvailable(i))
                {
                    dr2[0] = i;
                    dr2[1] = "可用";
                    dr2[2] = DateTime.Now;
                    dt.Rows.Add(dr2);
                }
                else
                {
                    dr2[0] = i;
                    dr2[1] = "不可用";
                    dr2[2] = DateTime.Now;
                    dt.Rows.Add(dr2);
                }
            }

            CheckFrmLoading.setIsLoad(true);
            CheckFrmLoading.FrmMainCacheDT = dt;
        }
        #endregion

        #region 改变按钮状态
        private void ChangeButtonState(bool State)
        {
            if (State)
            {
                BtnGetPort.Enabled = true;
            }
            else
            {
                BtnGetPort.Enabled = false;
            }
        }
        #endregion

        #region 关闭进程
        private bool KillProc(string strProcName)
        {
            bool IsKill = true;
            try
            {
                foreach (Process P in Process.GetProcessesByName(strProcName))
                {
                    if (!P.CloseMainWindow())
                    {
                        P.Kill();
                    }
                }
            }
            catch
            {
                Console.WriteLine("有问题哦！");
                IsKill = false;
            }
            return IsKill;
        }
        #endregion

        #region 获取进程启动用户
        public string getProcessOwnerName(int processId)
        {
            var processes = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_Process WHERE ProcessId = " + processId);
            foreach (System.Management.ManagementObject process in processes.Get())
            {
                try
                {
                    string[] OwnerInfo = new string[2];
                    process.InvokeMethod("GetOwner", (object[])OwnerInfo);
                    return OwnerInfo[0];
                }
                catch
                {
                    return string.Empty;
                }
            }

            return string.Empty;
        }
        #endregion

        #region 加载LvUsedPort已使用端口
        private void initLvUsedPort()
        {
            LvUsedPort.Clear();//清空先前内容
            LvUsedPort.View = View.Details;//分列显示
            LvUsedPort.GridLines = true;
            LvUsedPort.FullRowSelect = true;
            LvUsedPort.Columns.Add("协议");
            LvUsedPort.Columns.Add("本地地址");
            LvUsedPort.Columns.Add("外部地址");
            LvUsedPort.Columns.Add("状态");
            LvUsedPort.Columns.Add("PID");
            LvUsedPort.Columns.Add("程序名");
            LvUsedPort.Columns.Add("用户名");
            LvUsedPort.Columns.Add("程序路径");

            List<string> infoList = new List<string>();
            List<string> nameList = new List<string>();
            System.Diagnostics.ProcessStartInfo procInfo = new System.Diagnostics.ProcessStartInfo();
            System.Diagnostics.Process pro = new System.Diagnostics.Process();
            pro.StartInfo.FileName = "cmd";
            pro.StartInfo.UseShellExecute = false;
            pro.StartInfo.RedirectStandardInput = true;
            pro.StartInfo.RedirectStandardOutput = true;
            pro.StartInfo.RedirectStandardError = true;
            pro.StartInfo.CreateNoWindow = true;
            pro.Start();
            pro.StandardInput.WriteLine("netstat -ano");
            pro.StandardInput.WriteLine("exit");
            Regex reg = new Regex("\\s+", RegexOptions.Compiled);
            string line = "";
            infoList.Clear();
            nameList.Clear();
            while ((line = pro.StandardOutput.ReadLine()) != null)
            {
                line = line.Trim();
                if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
                {
                    line = reg.Replace(line, ",");
                    infoList.Add(line);
                }
                if (line.StartsWith("UDP", StringComparison.OrdinalIgnoreCase))
                {
                    line = reg.Replace(line, ",");
                    infoList.Add(line);
                }
                if (line.StartsWith("["))
                {
                    line = line.Replace("[", "");
                    line = line.Replace("]", "");
                    nameList.Add(line);
                }
                else if (line.StartsWith("无法"))
                {
                    nameList.Add("");
                }
            }

            pro.Close();
            List<PIDCache> pIDCachesList = new List<PIDCache>();
            Process p = new Process();
            for (int i = 0; i < infoList.Count; i++)
            {
                if (infoList[i].ToString().Split(',')[0] == "TCP")
                {
                    ListViewItem listItem = new ListViewItem();
                    listItem.Text = infoList[i].ToString().Split(',')[0];
                    listItem.SubItems.Add(infoList[i].Split(',')[1]);
                    listItem.SubItems.Add(infoList[i].Split(',')[2]);
                    listItem.SubItems.Add(infoList[i].Split(',')[3]);
                    listItem.SubItems.Add(infoList[i].Split(',')[4]);
                    int pid = Convert.ToInt32(infoList[i].Split(',')[4]);
                    string userName = "";
                    var pIDCachesListItem = pIDCachesList.Where(x => x.PID == pid).ToList().FirstOrDefault();
                    if (pIDCachesListItem != null)
                    {
                        userName = pIDCachesListItem.userName;
                    }
                    else
                    {
                        userName = getProcessOwnerName(pid);
                        PIDCache pIDCache = new PIDCache
                        {
                            PID = pid,
                            userName = userName
                        };
                        pIDCachesList.Add(pIDCache);
                    }

                    //listItem.SubItems.Add(GetFullPathByPid(pid));
                    //listItem.SubItems.Add(nameList[i]);
                    p = Process.GetProcessById(pid);
                    listItem.SubItems.Add(p.ProcessName);
                    listItem.SubItems.Add(userName);
                    if (!string.IsNullOrEmpty(userName) && userName != "SYSTEM")
                    {
                        listItem.SubItems.Add(p.MainModule.FileName);
                    }
                    else
                    {
                        listItem.SubItems.Add("");
                    }

                    this.LvUsedPort.Items.Add(listItem);
                }
                else if (infoList[i].ToString().Split(',')[0] == "UDP")
                {
                    ListViewItem listItem = new ListViewItem();
                    listItem.Text = infoList[i].ToString().Split(',')[0];
                    listItem.SubItems.Add(infoList[i].Split(',')[1]);
                    listItem.SubItems.Add(infoList[i].Split(',')[2]);
                    listItem.SubItems.Add("");
                    listItem.SubItems.Add(infoList[i].Split(',')[3]);
                    int pid = Convert.ToInt32(infoList[i].Split(',')[3]);
                    string userName = "";
                    var pIDCachesListItem = pIDCachesList.Where(x => x.PID == pid).ToList().FirstOrDefault();
                    if (pIDCachesListItem != null)
                    {
                        userName = pIDCachesListItem.userName;
                    }
                    else
                    {
                        userName = getProcessOwnerName(pid);
                        PIDCache pIDCache = new PIDCache
                        {
                            PID = pid,
                            userName = userName
                        };
                    }
                    //listItem.SubItems.Add(GetFullPathByPid(pid));
                    //listItem.SubItems.Add(nameList[i]);
                    p = Process.GetProcessById(pid);
                    listItem.SubItems.Add(p.ProcessName);
                    listItem.SubItems.Add(userName);
                    if (!string.IsNullOrEmpty(userName) && userName != "SYSTEM")
                    {
                        listItem.SubItems.Add(p.MainModule.FileName);
                    }
                    else
                    {
                        listItem.SubItems.Add("");
                    }

                    this.LvUsedPort.Items.Add(listItem);
                }
            }
        }
        #endregion

        private void BtnGetPort_Click(object sender, EventArgs e)
        {
            ChangeButtonState(false);
            Task taskinitDGVPortTable = new Task(() => initDGVPortTable());
            taskinitDGVPortTable.Start();
            taskinitDGVPortTable.ContinueWith(m =>
            {
                this.Invoke(new MethodInvoker(() =>
                {
                    DGVPortTable.DataSource = CheckFrmLoading.FrmMainCacheDT;
                    DGVPortTable.Columns[2].DefaultCellStyle.Format = ("yyyy/MM/dd HH:mm:ss:fff");
                    ChangeButtonState(true);
                }));
            });

            //CheckFrmLoading.setIsLoad(false);
            //FrmLoading frmLoading = new FrmLoading();
            //frmLoading.ShowDialog();

            //if (frmLoading.DialogResult == DialogResult.OK)
            //{
            //    DGVPortTable.DataSource = CheckFrmLoading.FrmMainCacheDT;
            //    DGVPortTable.Columns[2].DefaultCellStyle.Format = ("yyyy/MM/dd HH:mm:ss:fff");
            //}
        }

        private void TxtPort_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13)
            {
                DataTable dt = CheckFrmLoading.FrmMainCacheDT;
                if (dt == null)
                {
                    return;
                }
                try
                {
                string PortTxt = TxtPort.Text;
                if (!string.IsNullOrEmpty(PortTxt))
                {
                    string portLikeSql = "Port = '" + PortTxt + "'";

                    DataRow[] drArr = dt.Select(portLikeSql);

                    DataTable resultportLikeSQL = dt.Clone();

                    for (int i = 0; i < drArr.Length; i++)
                    {
                        resultportLikeSQL.ImportRow(drArr[i]);
                    }

                    DGVPortTable.DataSource = resultportLikeSQL;
                }
                else
                {
                    DGVPortTable.DataSource = dt;
                }
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }

        private void TxtIsUsed_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13)
            {
                DataTable dt = CheckFrmLoading.FrmMainCacheDT;
                if (dt == null)
                {
                    return;
                }
                string IsUsedTxt = TxtIsUsed.Text;
                if (!string.IsNullOrEmpty(IsUsedTxt))
                {
                    string IsUsedLikeSql = "IsUsed LIKE '%" + IsUsedTxt + "%'";

                    DataRow[] drArr = dt.Select(IsUsedLikeSql);

                    DataTable resultIsUsedLikeSQL = dt.Clone();

                    for (int i = 0; i < drArr.Length; i++)
                    {
                        resultIsUsedLikeSQL.ImportRow(drArr[i]);
                    }

                    DGVPortTable.DataSource = resultIsUsedLikeSQL;
                }
                else
                {
                    DGVPortTable.DataSource = dt;
                }
            }
        }

        private void BtnCloseProcess_Click(object sender, EventArgs e)
        {
            MessageBox.Show("禁止使用！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            return;
            bool IsKill = true;
            string[] killList = { "Test1", "Test2", "Test3", "Test4" };

            foreach (var strkillListProc in killList)
            {
                IsKill = KillProc(strkillListProc);
            }

            if (IsKill)
            {
                MessageBox.Show("所有进程关闭成功！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("有进程关闭失败哦！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            initLvUsedPort();
            BtnGetPort_Click(null, null);
        }

        private void BtnRefresh_Click(object sender, EventArgs e)
        {
            initLvUsedPort();
        }

        private void LvUsedPort_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            int sortColumn = -1;
            if (e.Column != sortColumn)
            {
                // Set the sort column to the new column.
                sortColumn = e.Column;
                // Set the sort order to ascending by default.
                LvUsedPort.Sorting = SortOrder.Ascending;
            }
            else
            {
                // Determine what the last sort order was and change it.
                if (LvUsedPort.Sorting == SortOrder.Ascending)
                {
                    LvUsedPort.Sorting = SortOrder.Descending;
                }
                else
                {
                    LvUsedPort.Sorting = SortOrder.Ascending;
                }
            }
            // Call the sort method to manually sort.
            LvUsedPort.Sort();
            // Set the ListViewItemSorter property to a new ListViewItemComparer
            // object.
            this.LvUsedPort.ListViewItemSorter = new ListViewItemComparer(e.Column, LvUsedPort.Sorting);
        }

        private void BtnOpenFloder_Click(object sender, EventArgs e)
        {
            int selectCount = LvUsedPort.SelectedItems.Count; //SelectedItems.Count就是：取得值，表示SelectedItems集合的物件数目。 
            if (selectCount > 0)//若selectCount大於0，说明用户有选中某列。
            {
                string xieyi = LvUsedPort.SelectedItems[0].SubItems[0].Text;
                string bendidizhi = LvUsedPort.SelectedItems[0].SubItems[1].Text;
                string waibudizhi = LvUsedPort.SelectedItems[0].SubItems[2].Text;
                string zhuangtai = LvUsedPort.SelectedItems[0].SubItems[3].Text;
                string PID = LvUsedPort.SelectedItems[0].SubItems[4].Text;
                string chengxvming = LvUsedPort.SelectedItems[0].SubItems[5].Text;
                string yonghuming = LvUsedPort.SelectedItems[0].SubItems[6].Text;
                string chengxvlujing = LvUsedPort.SelectedItems[0].SubItems[7].Text;

                if (!string.IsNullOrEmpty(yonghuming) && !string.IsNullOrEmpty(chengxvlujing) && yonghuming != "SYSTEM")
                {
                    Process p = Process.GetProcessById(Convert.ToInt32(PID));

                    //Process[] processes = System.Diagnostics.Process.GetProcesses();//获取系统进程;
                    //foreach (Process process in processes)
                    //{
                    //    if (process.ProcessName == chengxvming)//获取指定进程名的路径
                    //    {
                    //        string processPath = Path.GetDirectoryName(process.MainModule.FileName);
                    //        System.Diagnostics.Process.Start("Explorer.exe", processPath);
                    //        break;
                    //    }
                    //}

                    string ProcPath = System.IO.Path.GetDirectoryName(p.MainModule.FileName);//Process.GetCurrentProcess().MainModule.FileName));
                    System.Diagnostics.Process.Start("Explorer.exe", ProcPath);
                }
            }
        }

        private void BtnKillProc_Click(object sender, EventArgs e)
        {
            int selectCount = LvUsedPort.SelectedItems.Count; //SelectedItems.Count就是：取得值，表示SelectedItems集合的物件数目。 
            if (selectCount > 0)//若selectCount大於0，说明用户有选中某列。
            {
                string xieyi = LvUsedPort.SelectedItems[0].SubItems[0].Text;
                string bendidizhi = LvUsedPort.SelectedItems[0].SubItems[1].Text;
                string waibudizhi = LvUsedPort.SelectedItems[0].SubItems[2].Text;
                string zhuangtai = LvUsedPort.SelectedItems[0].SubItems[3].Text;
                string PID = LvUsedPort.SelectedItems[0].SubItems[4].Text;
                string chengxvming = LvUsedPort.SelectedItems[0].SubItems[5].Text;
                string yonghuming = LvUsedPort.SelectedItems[0].SubItems[6].Text;
                string chengxvlujing = LvUsedPort.SelectedItems[0].SubItems[7].Text;

                if (!string.IsNullOrEmpty(yonghuming) && !string.IsNullOrEmpty(chengxvlujing) && yonghuming != "SYSTEM")
                {
                    Process p = Process.GetProcessById(Convert.ToInt32(PID));

                    //Process[] processes = System.Diagnostics.Process.GetProcesses();//获取系统进程;
                    //foreach (Process process in processes)
                    //{
                    //    if (process.ProcessName == chengxvming)//获取指定进程名的路径
                    //    {
                    //        string processPath = Path.GetDirectoryName(process.MainModule.FileName);
                    //        System.Diagnostics.Process.Start("Explorer.exe", processPath);
                    //        break;
                    //    }
                    //}

                    p.Kill();
                    initLvUsedPort();
                }
            }
        }

        private void CbbIsUsed_SelectedIndexChanged(object sender, EventArgs e)
        {
            string selectCbbIsUsed = CbbIsUsed.Text;
            DataTable dt = CheckFrmLoading.FrmMainCacheDT;
            if(dt ==null)
            {
                return;
            }

            if(selectCbbIsUsed =="请选择")
            {
                DGVPortTable.DataSource = dt;
            }
            else
            {
                if(!string.IsNullOrEmpty(selectCbbIsUsed))
                {
                    string IsUsedLikeSql = "IsUsed LIKE '"+selectCbbIsUsed+"'";

                    DataRow[] drArr = dt.Select(IsUsedLikeSql);

                    DataTable resultIsUsedLikeSQL = dt.Clone();

                    for (int i = 0; i < drArr.Length; i++)
                    {
                        resultIsUsedLikeSQL.ImportRow(drArr[i]);
                    }

                    DGVPortTable.DataSource = resultIsUsedLikeSQL;
                }
                else
                {
                    DGVPortTable.DataSource = dt;
                }
            }
        }
    }
    public class ListViewItemComparer : IComparer
    {
        private int col;
        private SortOrder order;
        public ListViewItemComparer()
        {
            col = 0;
            order = SortOrder.Ascending;
        }
        public ListViewItemComparer(int column, SortOrder order)
        {
            col = column;
            this.order = order;
        }
        public int Compare(object x, object y)
        {
            int returnVal = -1;
            float a = 0, b = 0;
            if (float.TryParse(((ListViewItem)x).SubItems[col].Text, out a) && float.TryParse(((ListViewItem)y).SubItems[col].Text, out b))
            {
                returnVal = a >= b ? (a == b ? 0 : 1) : -1;
                if (order == SortOrder.Descending)
                {
                    returnVal *= -1;
                }
            }
            else
            {
                returnVal = String.Compare(((ListViewItem)x).SubItems[col].Text,
                                        ((ListViewItem)y).SubItems[col].Text);
                // Determine whether the sort order is descending.
                if (order == SortOrder.Descending)
                {
                    // Invert the value returned by String.Compare.
                    returnVal *= -1;
                }
            }
            return returnVal;
        }
    }

    public class PIDCache
    {
        public int PID { get; set; }
        public string userName { get; set; }
    }
}
